package com.zeratul.common.mybatis.core.sqlexec.interceptor;

import cn.hutool.core.util.ObjectUtil;
import com.zeratul.common.mybatis.core.sqlexec.context.SqlContext;
import com.zeratul.common.mybatis.core.sqlexec.prop.LogType;
import com.zeratul.common.mybatis.core.sqlexec.prop.ZtExecSqlConfiguration;
import com.zeratul.web.interceptor.base.BaseHandlerInterceptor;
import com.zeratul.web.utils.ServletUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.AntPathMatcher;

import java.util.List;
import java.util.Optional;

/**
 * 是否记录SQL日志的拦截器
 */
@RefreshScope
public class SqlLogInterceptor extends BaseHandlerInterceptor {

    @Autowired
    private ZtExecSqlConfiguration sqlConfiguration;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //是否输出SQL日志，默认不输出
        boolean isPrint = false;

        //判断是否需要输出sql日志
        if (LogType.API == sqlConfiguration.getLogType()) {
            //获取需要输入SQL日志的url
            List<String> apis = sqlConfiguration.getApis();

            if (ObjectUtil.isNotEmpty(sqlConfiguration.getApis())) {
                //请求的Url
                String reqUrl = getURL();
                //获取不到请求Url，则直接放行
                for (String api : apis) {
                    if (antPathMatcher.match(api, reqUrl)) {
                        //匹配上URL，则直接标记为true，需要输出SQL
                        isPrint = true;
                        break;
                    }
                }
            }
        } else {
            //默认输出所有sql
            isPrint = true;
        }

        //获取请求参数，如果有参数sql-log，并且值为true，则输出sql日志，否则直接放行
        boolean sqlLog = getParams(sqlConfiguration.getHeaderName());
        isPrint = sqlLog || isPrint;

        //设置标志上下文
        SqlContext.setSqlLog(isPrint);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        SqlContext.clear();
    }

    /**
     * 获取当前请求的Api
     * @return
     */
    private String getURL(){
        return Optional.ofNullable(ServletUtils.getRequest())
                .map(HttpServletRequest::getRequestURI)
                .orElse(null);
    }

    /**
     * 获取请求参数
     * @return
     */
    private Boolean getParams(String paramName){
        return Optional.ofNullable(ServletUtils.getParameterToBool(paramName))
                .orElse(false);
    }

    /**
     * 拦截器的拦截Path路径
     *
     * @return
     */
    @Override
    public String path() {
        return "/**";
    }
}
